home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 436_01 / infloat.c < prev    next >
Text File  |  1994-10-07  |  15KB  |  557 lines

  1. /*************************************************************************
  2.     Source file:  INFLOAT.C
  3.  
  4.     INCON floating-point input handler.
  5.  
  6.     Compiler:  Borland Turbo C 2.01
  7.  
  8.     INCON source files and the object and library files created from
  9.     them are:
  10.         Copyright (c) 1993-94, Richard Zigler.
  11.     You may freely distribute unmodified source, object, and library
  12.     files, and incorporate them into your own non-commercial software,
  13.     provided that this paragraph and the program name and copyright
  14.     strings defined in INCON.C are included in all copies.
  15. *************************************************************************/
  16.  
  17. #include <ctype.h>                            /* character classification        */
  18. #include <string.h>
  19. #include "indefs.h"                            /* globals and definitions            */
  20. #include "incon.h"                            /* state definitions                    */
  21. #include "indecl.h"                            /* public utility routines            */
  22.  
  23. /**** Local Data ****/
  24.  
  25. enum                                                /* float field fix-up constants    */
  26.             {
  27.             FLT_INIT                        ,        /* initialize field for display    */
  28.             FLT_FIX                        ,        /* fix field left of decimal        */
  29.             FLT_MOV                        ,        /* move chars left of decimal        */
  30.             FLT_PAD                        ,        /* pad out field with zeros        */
  31.             }                                ;
  32.  
  33. static BFLAG                Point        ;        /* decimal point entered yet?        */
  34. static short                PointNdx    ;        /* decimal point index                */
  35. static BFLAG                Sign        ;        /* sign entered yet?                    */
  36. static short                SignNdx    ;        /* numeric sign index                */
  37.  
  38. /**** Local Routines ****/
  39.  
  40. static int near pascal    FloatFix
  41.                 (
  42.                 int            Op,                /* operation requested                */
  43.                 int            Pos                /* index into string                    */
  44.                 )                ;
  45.  
  46. int pascal hFloatField( STATES State, register int Pos )
  47. {
  48. register int    max_width = Width - 1;
  49. int                old_pos = Pos;
  50.  
  51. switch( State )
  52.     {
  53.     case stError:
  54.         break;
  55.  
  56.     case stQuit:                                /* [Enter] -- end input                */
  57.         Chr = 0;
  58.         goto __FloatExit;
  59.  
  60.     case stInit:                                /* field initialization                */
  61.         SignNdx = 0;
  62.         Point = Sign = NO;
  63.         StrLength = Width;
  64.         if ( !Prec )
  65.             {
  66.             Prec = strchr( OutStr, '.' ) - OutStr;
  67.             Prec = StrLength - Prec - 1;
  68.             }
  69.         PointNdx = Width - Prec - 1;
  70.         if ( !PointNdx )
  71.             {
  72.             --Prec;                                /* force at least one decimal        */
  73.             ++PointNdx;                            /*  digit position                    */
  74.             }
  75.         if ( PointNdx > 0 )
  76.             {
  77.             Flags.Confirm    =
  78.             Flags.Display    = YES;
  79.             Pos = FloatFix( FLT_INIT, 0 );
  80.             }
  81.         return ( Pos );
  82.  
  83.     case stFieldClear:                        /* [Esc] -- clear field or exit    */
  84.         if ( EscSet)
  85.             More = NO;
  86.         else
  87.             {
  88.             memset( OutStr, Fill, Width );
  89.             OutStr[PointNdx] = '.';
  90.             Pos        =
  91.             SignNdx    =
  92.             Sign        = 0;
  93.             ++Update;
  94.             }
  95.         break;
  96.  
  97.     case stDeleteCharLeft:                    /* [Backspace] -- delete left        */
  98.         if ( Pos )
  99.             {
  100.             --Move;
  101.             if ( Pos == max_width && OutStr[Pos] != (char)Fill )
  102.                 OutStr[Pos] = Fill;
  103.             else if ( --Pos == PointNdx )
  104.                 OutStr[--Pos] = Fill;
  105.             else
  106.                 {
  107.                 if ( Pos < PointNdx )
  108.                     max_width = PointNdx - 1;
  109.                 goto __MoveCharsToCursor;
  110.                 }
  111.             }
  112.         break;
  113.  
  114.     case stMoveToStart:                        /* [Home] -- start of field        */
  115.         if ( Pos )
  116.             {
  117.             Pos = 0;
  118.             --Move;
  119.             }
  120.         break;
  121.  
  122.     case stMoveCharLeft:                        /* [Left Arrow] -- move char lt    */
  123.         if ( Pos )
  124.             {
  125.             if ( --Pos <= SignNdx )
  126.                 Pos = 0;
  127.             --Move;
  128.             }
  129.         break;
  130.  
  131.     case stMoveCharRight:                    /* [Right Arrow] -- move char rt    */
  132.         if ( Pos < max_width )
  133.             {
  134.             ++Pos;
  135.             ++Move;
  136.             }
  137.         break;
  138.  
  139.     case stMoveToEnd:                            /* [End] -- end of field            */
  140.         if ( Pos < max_width )
  141.             {
  142.             Pos = max_width;
  143.             ++Move;
  144.             }
  145.         break;
  146.  
  147.     case stMoveWordLeft:                        /* [Ctrl Left] -- move word lt    */
  148.         if ( Pos )
  149.             {
  150.             Pos = Pos > PointNdx + 1 ? PointNdx + 1 : 0 ;
  151.             --Move;
  152.             }
  153.         break;
  154.  
  155.     case stMoveWordRight:                    /* [Ctrl Right] -- move word rt    */
  156.         if ( Pos < max_width )
  157.             {
  158.             Pos = Pos < PointNdx ? PointNdx + 1 : max_width ;
  159.             ++Move;
  160.             }
  161.         break;
  162.  
  163.     case stDeleteWordLeft:                    /* [Ctrl L] -- delete word left    */
  164.         if ( Pos == (PointNdx + 1) )
  165.             Pos = PointNdx - 1;
  166.         max_width = Pos;
  167.         Pos = Pos > PointNdx ? PointNdx + 1 : 0 ;
  168.         goto __DeleteWord;
  169.  
  170.     case stDeleteWordRight:                    /* [Ctrl R] -- delete word right    */
  171.         if ( Pos == (PointNdx - 1) )
  172.             Pos = PointNdx + 1;
  173.         if ( Pos < PointNdx )
  174.             max_width = PointNdx - 1;        /* fall through to __DeleteWord    */
  175.  
  176.     case stDeleteToEnd:                        /* [Ctrl End] -- clear to end        */
  177.  
  178. __DeleteWord:
  179. ;
  180.         memset( OutStr + Pos, Fill, max_width - Pos + 1 );
  181.         OutStr[PointNdx] = '.';
  182.         ++Update;
  183.         break;
  184.  
  185.     case stDeleteToStart:                    /* [Ctrl Home] -- clear to start    */
  186.         max_width = Pos;
  187.         Pos = 0;
  188.         goto __DeleteWord;
  189.  
  190.     case stDeleteAtCursor:                    /* [Del] -- delete at cursor        */
  191.         if ( Pos < PointNdx )
  192.             max_width = PointNdx - 1;
  193.         ++Update;
  194.  
  195. __MoveCharsToCursor:
  196. ;
  197.         memcpy( OutStr + Pos, OutStr + Pos + 1, max_width - Pos );
  198.         OutStr[max_width] = Fill;
  199.         break;
  200.  
  201.     case stExitPlus:                            /* [Keypad +] -- special exit        */
  202.     case stExitMinus:                            /* [Keypad -] -- special exit        */
  203.  
  204.         /****
  205.             If cursor is to right of sign position or Sign flag
  206.             is off, treat these keys as exits; otherwise convert
  207.             Chr to '+' or '-' and fall through to stCharMatch.
  208.         ****/
  209.  
  210.         if ( Pos > SignNdx || !Flags.Sign )
  211.             {
  212.  
  213. __FloatExit:
  214. ;
  215.             FloatFix( FLT_FIX, PointNdx    );
  216.             FloatFix( FLT_PAD, 0                );
  217.             More = NO;
  218.             ++Update;
  219.             break;
  220.             }
  221.         else
  222.             Chr = (State == stExitPlus) ? '+' : '-' ;
  223.  
  224.     case stCharMatch:                            /* see if entry matches field        */
  225.         if
  226.             (
  227.             isdigit( Chr )
  228.             ||
  229.             ( (Chr == '+' || Chr == '-') && Pos <= SignNdx && Flags.Sign )
  230.             ||
  231.             ( !Point && Chr == '.' )
  232.             )
  233.             {
  234.             if ( InBegin )
  235.                 Pos = hFloatField( stFieldClear, 0 );
  236.             if ( Chr == '+' || Chr == '-' )
  237.                 {
  238.                 Sign        = Chr;
  239.                 SignNdx    = Pos;
  240.                 }
  241.             if ( Chr == '.' )
  242.                 {
  243.                 FloatFix( FLT_FIX, Pos );
  244.                 Pos = PointNdx + 1;
  245.                 memset( OutStr + Pos, Fill, Prec );
  246.                 }
  247.             else
  248.                 OutStr[Pos++] = Chr;
  249.             ++Move;
  250.          }                                        /* if (isdigit)                        */
  251.         else
  252.             State = stError;
  253.         break;
  254.     }                                                /* switch                                */
  255.  
  256. if ( Pos >= Width )
  257.     Pos = Width - 1;
  258. if ( Pos == PointNdx )
  259.     Pos += Move;                                /* move left or right past sign    */
  260. Point = (Pos >= PointNdx);
  261.  
  262. if ( Move )
  263.     {
  264.  
  265.     /****
  266.         If the cursor has passed to the left of the sign (or
  267.         implied sign) position, FloatFix() moves the integer
  268.         portion of OutStr to the beginning of the field and
  269.         fills vacant digit positions with Fill.
  270.     ****/
  271.  
  272.     if ( Pos <= SignNdx )
  273.         Pos = FloatFix( FLT_MOV, PointNdx );
  274.  
  275.     /****
  276.         If the cursor has passed to the right over the decimal
  277.         point, FloatFix() closes gaps in the integer portion of
  278.         OutStr and moves that part of the string adjacent to the
  279.         point.  After the call to FloatFix(), all fill characters
  280.         to the left of the decimal point have been replaced by
  281.         digits, sign, or spaces, so FloatFix() is not called on
  282.         subsequent moves while the cursor is still to the right
  283.         of the decimal.
  284.     ****/
  285.  
  286.     if    ( Move > 0 && Pos > PointNdx )
  287.         {
  288.         if ( memchr( OutStr, Fill, PointNdx ) )
  289.             FloatFix( FLT_FIX, PointNdx );
  290.         }
  291.  
  292.     /****
  293.         If the cursor has passed to the left over the decimal
  294.         point, FloatFix() closes gaps in the decimal portion
  295.         of OutStr and pads it with zeros.  After the call to
  296.         FloatFix(), all fill characters to the right of the
  297.         decimal point have been replaced by digits, so
  298.         FloatFix() is not called on subsequent moves while
  299.         the cursor is still to the left of the decimal.
  300.     ****/
  301.  
  302.     else if ( Move < 0 && Pos < PointNdx && old_pos > PointNdx )
  303.         {
  304.         if ( memchr( OutStr + PointNdx + 1, Fill, Prec ) )
  305.             FloatFix( FLT_PAD, PointNdx );
  306.         }
  307.     ++Update;
  308.     Move = NO;
  309.    }                                                /* if(Move)                                */
  310. return( Pos );
  311. }                                                    /**** hFloatField()                ****/
  312.  
  313. /*************************************************************************
  314.     FloatFix()
  315.     Patches up the output string in floating-point fields.
  316. *************************************************************************/
  317.  
  318. static int near pascal FloatFix
  319. (
  320.             int        Op,                        /* operation requested                */
  321. register int        Pos                        /* index into string                    */
  322. )
  323. {
  324.             BYTE        c